/************************************************************************

								Heroes IV
					  Copyright 2001, The 3DO Company

	------------------------------------------------------------------
  						  dialog_caravan_creation.cpp

	$Header: $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "dialog_caravan_creation.h"

#include "adaptor_handler.h"
#include "adventure_frame.h"
#include "adventure_map.h"
#include "adventure_map_window.h"
#include "adventure_object.h"
#include "adventure_path_finder.h"
#include "army.h"
#include "army_ptr.h"
#include "bitmap_layer_cache.h"
#include "bitmap_layer_window.h"
#include "bitmap_group.h"
#include "bitmap_group_cache.h"
#include "bound_handler.h"
#include "buffer_window.h"
#include "button.h"
#include "button_cache.h"
#include "caravan.h"
#include "creature.h"
#include "creature_array.h"
#include "creature_array_window.h"
#include "creature_icon_window.h"
#include "external_string.h"
#include "footprint.h"
#include "format_string.h"
#include "elements_of.h"
#include "hero_keyword_replacer.h"
#include "interface_help.h"
#include "item_help_block.h"
#include "micro_map_window.h"
#include "minimum_maximum.h"
#include "pathfinding_subject.h"
#include "player.h"
#include "replace_keywords.h"
#include "resurrect_heroes.h"
#include "scrollbar.h"
#include "simple_dialog.h"
#include "square.h"
#include "standard_fonts.h"
#include "text_window.h"
#include "toggle_button.h"
#include "town_window.h"

extern t_external_string const k_hotkey_buy;
extern t_button_cache g_ok_button;
extern t_button_cache g_cancel_button;
extern t_button_cache g_divide_button;
extern t_button_cache g_divide_single_button;
extern t_button_cache const k_buy_button;
extern t_bitmap_group_cache g_town_list_bitmaps;
extern t_bitmap_layer_cache g_town_marker;
extern t_external_string const k_text_resurrect_heroes;

namespace
{
	t_external_string const k_caravan_no_other_locations( "caravan.no_other_locations" );
	t_external_string const k_caravan_no_other_locations_allied( "caravan.no_other_locations_allied" );
	t_external_string const k_caravan_no_owned_troops( "caravan.no_owned_troops" );
	t_external_string const k_caravan_title( "caravan.title" );
	t_external_string const k_caravan_source_title( "caravan.source_title" );
	t_external_string const k_caravan_destination_title( "caravan.destination_title" );
	t_external_string const k_caravan_location_title( "caravan.location_title" );
	t_external_string const k_caravan_from_town_text( "caravan.from_town_text" );
	t_external_string const k_caravan_to_town_text( "caravan.to_town_text" );
	t_external_string const k_caravan_unreachable_location_title( "caravan.unreachable_location_title" );
	t_external_string const k_caravan_garrison_title( "caravan.garrison_title" );
	t_external_string const k_caravan_new_caravan_title( "caravan.new_caravan_title" );
	t_external_string const k_caravan_buy_none_1_day( "caravan.buy_none_1_day" );
	t_external_string const k_caravan_buy_none_multiple_days( "caravan.buy_none_multiple_days" );
	t_external_string const k_caravan_buy_none_permenantly_blocked( "caravan.buy_none_permenantly_blocked" );
	t_external_string const k_caravan_buy_none_blocked_by_enemy( "caravan.buy_none_blocked_by_enemy" );
	t_external_string const k_caravan_buy_one_1_day( "caravan.buy_one_1_day" );
	t_external_string const k_caravan_buy_one_multiple_days( "caravan.buy_one_multiple_days" );
	t_external_string const k_caravan_buy_one_permenantly_blocked( "caravan.buy_one_permenantly_blocked" );
	t_external_string const k_caravan_buy_one_blocked_by_enemy( "caravan.buy_one_blocked_by_enemy" );
	t_external_string const k_caravan_buy_multiple_1_day( "caravan.buy_multiple_1_day" );
	t_external_string const k_caravan_buy_multiple_multiple_days( "caravan.buy_multiple_multiple_days" );
	t_external_string const k_caravan_buy_multiple_permenantly_blocked( "caravan.buy_multiple_permenantly_blocked" );
	t_external_string const k_caravan_buy_multiple_blocked_by_enemy( "caravan.buy_multiple_blocked_by_enemy" );
	t_external_string const k_caravan_reachable_1_day_text( "caravan.reachable_1_day_text" );
	t_external_string const k_caravan_reachable_multiple_day_text( "caravan.reachable_multiple_days_text" );
	t_external_string const k_caravan_permenantly_blocked_text( "caravan.permenantly_blocked_text" );
	t_external_string const k_caravan_blocked_by_enemy_text( "caravan.blocked_by_enemy_text" );
	t_external_string const k_caravan_change_without_sending_text( "caravan.change_without_sending_text" );
	t_external_string const k_caravan_cancel_without_sending_text( "caravan.cancel_without_sending_text" );
	t_external_string const k_caravan_could_not_merge( "caravan.merge_failure" );
	t_external_string const k_dwelling_caravan_sent_1_day( "caravan.dwelling_caravan_sent_1_day" );
	t_external_string const k_dwelling_caravan_sent_multiple_days( "caravan.dwelling_caravan_sent_multiple_days" );
	t_bitmap_group_cache const k_bitmaps( "dialog.caravan_create" );
};

// ---------------------------------------------------------------------------
// Treat any type of location as an adventure object
// ---------------------------------------------------------------------------
t_dialog_caravan_creation::t_location_ptr::operator t_adventure_object*()
{
	if ( is_town )
		return object.town;
	else
		return object.dwelling;
}

// ---------------------------------------------------------------------------
// Treat any type of location as an adventure object
// ---------------------------------------------------------------------------
t_adventure_object *t_dialog_caravan_creation::t_location_ptr::operator->()
{
	if ( is_town )
		return object.town;
	else
		return object.dwelling;
}

// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
t_dialog_caravan_creation::t_dialog_caravan_creation( t_adventure_map      * map,
													  t_town_window		   * parent,
													  t_town			   * town )
	: t_window( k_completely_transparent, parent ),
	  m_image_creator( t_adv_object_list_image::k_mode_caravan ),
	  m_map( map ),
	  m_parent_town_window( parent ),
	  m_town( town ),
	  m_town_pathfinder( *map )
{
}

// ---------------------------------------------------------------------------
// Initialize dialog. Return true if successful, false if not
// ---------------------------------------------------------------------------
bool t_dialog_caravan_creation::init_dialog()
{
	int player_number = m_map->get_player_number();
	t_player & player = m_map->get_player();
	bool disable_origins = false;

	if ( m_town->get_owner_number() != player_number )
	{
		disable_origins = true; // Can't caravan _to_ an allied town, only from

		t_army * trading_army = m_parent_town_window->get_trading_army( m_town );

		if (   trading_army == NULL 
			|| trading_army->get_owner_number() != player_number )
		{
			ok_dialog( k_caravan_no_owned_troops, true );
			return false;
		}
	}

	m_selected_location[ k_location_type_origin ] = 0;
	m_selected_location[ k_location_type_destination ] = 0;

	// Determine all legit origins and destinations
	t_town_list * towns = player.get_towns();

	t_town_list::iterator town_index;

	for ( town_index = towns->begin(); town_index != towns->end(); town_index++ )
	{
		// Both source & destination must have caravan structures for town->town caravaning
		if ( town_index->get() != m_town && (*town_index)->has( k_town_caravan ) )
		{
			m_locations[ k_location_type_destination ].push_back( *town_index );

			if ( !disable_origins )
				m_locations[ k_location_type_origin ].push_back( *town_index );
		}
	}

	if ( !disable_origins )
	{
		t_adv_dwelling_list const & dwellings = player.get_dwellings();

		t_adv_dwelling_list::const_iterator dwelling_index;

		for ( dwelling_index = dwellings.begin(); dwelling_index != dwellings.end(); dwelling_index++ )
		{
			m_locations[ k_location_type_origin ].push_back( *dwelling_index );
		}
	}

	if ( m_locations[ k_location_type_origin ].size() == 0 && m_locations[ k_location_type_destination ].size() == 0 ) 
	{
		if ( m_town->get_owner_number() != player_number )
			ok_dialog( k_caravan_no_other_locations_allied, true );
		else
			ok_dialog( k_caravan_no_other_locations, true );
		return false;
	}

	// Set up pathfinders 
	t_location_vector::iterator origin_index;

	for (origin_index = m_locations[ k_location_type_origin ].begin(); origin_index != m_locations[ k_location_type_origin ].end(); origin_index++ )
	{
		t_shared_ptr< t_adventure_path_finder > pathfinder_ptr( new t_adventure_path_finder( *m_map ) );

		m_origin_path_finders.push_back( pathfinder_ptr );

		m_origin_permenantly_blocked.push_back( !setup_pathfinder( *origin_index, *pathfinder_ptr ) );
	}

	// Same for target town
	m_town_permenantly_blocked = !setup_pathfinder( m_town, m_town_pathfinder );

	// Create subwindows
	m_bitmaps = k_bitmaps.get();
	t_help_block const& help = get_help_block( "caravan_create" );
	t_item_help const * help_item;
	t_keyword_replacer town_replacer;

	t_bitmap_layer const * layer;
	t_window *             background;
	t_text_window *		   text_window;
	t_buffer_window *	   buffer_window;
	t_button *             button;
	int					   i;

	town_replacer.add_keyword("%town", m_town->get_name() );

	layer = m_bitmaps->find( "background" );
	background = new t_bitmap_layer_window( layer, t_screen_point(0, 0), this );

	layer = m_bitmaps->find( "title" );
	text_window = new t_text_window( get_font( 20 ), layer->get_rect(), background, k_caravan_title, t_pixel_24(0,0,0) );
	text_window->set_drop_shadow( false );
	text_window->set_justification( k_justify_center );

	layer = m_bitmaps->find ("text scroll" );
	m_text_background = new t_bitmap_layer_window( layer, t_screen_point(0, 0), background );

	layer = m_bitmaps->find( "text" );
	m_text_window = new t_text_window( get_font( 18 ), layer->get_rect(), background, "", t_pixel_24(0,0,0) );
	m_text_window->set_drop_shadow( false );
	m_text_window->set_justification( k_justify_center );

	layer = m_bitmaps->find ("buy_text_scroll" );
	m_buy_text_background = new t_bitmap_layer_window( layer, t_screen_point(0, 0), background );

	layer = m_bitmaps->find( "buy_text" );
	m_buy_text_window = new t_text_window( get_font( 18 ), layer->get_rect(), background, "", t_pixel_24(0,0,0) );
	m_buy_text_window->set_drop_shadow( false );
	m_buy_text_window->set_justification( k_justify_center );

	layer = m_bitmaps->find( "target_town_name" );
	text_window = new t_text_window( get_font( 18 ), layer->get_rect(), background, m_town->get_name(), t_pixel_24(0,0,0) );
	text_window->set_drop_shadow( false );
	text_window->set_justification( k_justify_center );

	// Create target town map & picture
	m_image_creator.set_town( m_town );
	t_bitmap_group *	   town_list_bitmaps = g_town_list_bitmaps.get();

	layer = m_bitmaps->find( "target_town_picture" );
	buffer_window = new t_buffer_window( layer->get_rect().top_left(), background );
	buffer_window->set_bitmap( m_image_creator.get_bitmap() );
   	set_help( buffer_window, help, "town" );

	layer = m_bitmaps->find( "target_town_map" );
	t_screen_rect map_rect = layer->get_rect();
	t_micro_map_window * map_window = new t_micro_map_window( map_rect.top_left(), background );
	map_window->set_renderer(
		&m_image_creator.get_map_renderer( *m_map, m_map->get_player().get_team(), map_rect.size(), g_town_marker.get() ) );
   	set_help( map_window, help, "mini_mini_map" );

	layer = m_bitmaps->find( "target_town_frame" );
	new t_bitmap_layer_window( layer, t_screen_point(0, 0), background );

	layer = m_bitmaps->find( "scrollbar" );
	m_scrollbar = new t_scrollbar( layer->get_rect().top_left(), layer->get_rect().height(),
								   background, 0, 0 );
	m_scrollbar->set_handler( bound_handler( *this, &t_dialog_caravan_creation::scroll ) );
	m_scrollbar->set_page_size( k_displayed_locations );

	layer = m_bitmaps->find( "garrison_text_background" );
	m_garrison_title_background = new t_bitmap_layer_window( layer, t_screen_point(0, 0), background );

	layer = m_bitmaps->find( "garrison_text" );
	m_garrison_title = new t_text_window( get_font( 16 ), layer->get_rect(), background, k_caravan_garrison_title, t_pixel_24(0,0,0) );
	m_garrison_title->set_drop_shadow( false );
	m_garrison_title->set_justification( k_justify_center );

	layer = m_bitmaps->find( "caravan_text_background" );
	m_caravan_title_background = new t_bitmap_layer_window( layer, t_screen_point(0, 0), background );

	layer = m_bitmaps->find( "caravan_text" );
	m_caravan_title = new t_text_window( get_font( 16 ), layer->get_rect(), background, k_caravan_new_caravan_title, t_pixel_24(0,0,0) );
	m_caravan_title->set_drop_shadow( false );
	m_caravan_title->set_justification( k_justify_center );

	layer = m_bitmaps->find( "ok_button" );
	button = new t_button( g_ok_button.get(), layer->get_rect().top_left(), background );
	button->set_click_handler( bound_handler( *this, &t_dialog_caravan_creation::ok_clicked ) );
  set_help( button, help, "ok" );

	layer = m_bitmaps->find( "cancel_button" );
	button = new t_button( g_cancel_button.get(), layer->get_rect().top_left(), background );
	button->set_click_handler( bound_handler( *this, &t_dialog_caravan_creation::cancel_clicked ) );
  set_help( button, help, "cancel" );

	layer = m_bitmaps->find( "double_ring_background" );
	m_double_rings = new t_bitmap_layer_window( layer, t_screen_point(0, 0), background );

	layer = m_bitmaps->find( "single_ring_background" );
	m_single_rings = new t_bitmap_layer_window( layer, t_screen_point(0, 0), background );

	layer = m_bitmaps->find( "caravan_ring_background" );
	m_caravan_rings = new t_bitmap_layer_window( layer, t_screen_point(0, 0), background );

	layer = m_bitmaps->find( "double_split_button" );
	m_double_split_button = new t_toggle_button( g_divide_button.get(), layer->get_rect().top_left(), background );
	m_double_split_button->set_click_handler( bound_handler( *this, &t_dialog_caravan_creation::split_clicked ) );
   	set_help( m_double_split_button, help, "split" );

	layer = m_bitmaps->find( "single_split_button" );
	m_single_split_button = new t_toggle_button( g_divide_single_button.get(), layer->get_rect().top_left(), background );
	m_single_split_button->set_click_handler( bound_handler( *this, &t_dialog_caravan_creation::split_clicked ) );
   	set_help( m_single_split_button, help, "split" );

	m_transport_button = create_button( m_bitmaps, "transport", background );
	m_transport_button->set_click_handler( bound_handler( *this, &t_dialog_caravan_creation::send_clicked ) );
   	set_help( m_transport_button, help, "transport" );

	m_move_garrison_to_caravan_button = create_button( m_bitmaps, "move_to_caravan_double_1", background );
	m_move_garrison_to_caravan_button->set_click_handler( bound_handler( *this, &t_dialog_caravan_creation::move_garrison_to_caravan_clicked ) );
   	set_help( m_move_garrison_to_caravan_button, help, "Move_Garrison_To_Caravan" );

	m_move_visiting_to_caravan_button = create_button( m_bitmaps, "move_to_caravan_double_2", background );
	m_move_visiting_to_caravan_button->set_click_handler( bound_handler( *this, &t_dialog_caravan_creation::move_visiting_to_caravan_clicked ) );
   	set_help( m_move_visiting_to_caravan_button, help, "Move_Visiting_To_Caravan" );

	m_move_single_to_caravan_button = create_button( m_bitmaps, "move_to_caravan_single", background );
	m_move_single_to_caravan_button->set_click_handler( bound_handler( *this, &t_dialog_caravan_creation::move_single_to_caravan_clicked ) );

	m_move_caravan_button = create_button( m_bitmaps, "move_back", background );
	m_move_caravan_button->set_click_handler( bound_handler( *this, &t_dialog_caravan_creation::move_caravan_clicked ) );
   	set_help( m_move_caravan_button, help, "Move_Caravan" );

	layer = m_bitmaps->find( "from_town_released" );
	m_from_town_button = new t_toggle_button( layer->get_rect().top_left(), background );
	set_button_layers( m_from_town_button, m_bitmaps, "from_town" );
	m_from_town_button->set_click_handler( bound_handler( *this, &t_dialog_caravan_creation::from_town_clicked ) );
	if ( m_locations[ k_location_type_destination ].empty() )
		m_from_town_button->enable( false );
	help_item = &help["from_town"];
	m_from_town_button->set_help_balloon_text( town_replacer( help_item->name ) );
	m_from_town_button->set_right_click_text( town_replacer( help_item->help_text ) );

	layer = m_bitmaps->find( "from_town_text" );
	text_window = new t_text_window( get_font( 16 ), layer->get_rect(), background, k_caravan_from_town_text, t_pixel_24(0,0,0) );
	text_window->set_drop_shadow( false );
	text_window->set_justification( k_justify_center );
	
	layer = m_bitmaps->find( "to_town_released" );
	m_to_town_button = new t_toggle_button( layer->get_rect().top_left(), background );
	set_button_layers( m_to_town_button, m_bitmaps, "to_town" );
	m_to_town_button->set_click_handler( bound_handler( *this, &t_dialog_caravan_creation::to_town_clicked ) );
	if ( m_locations[ k_location_type_origin ].empty() )
		m_to_town_button->enable( false );
	help_item = &help["to_town"];
	m_to_town_button->set_help_balloon_text( town_replacer( help_item->name ) );
	m_to_town_button->set_right_click_text( town_replacer( help_item->help_text ) );
	
	layer = m_bitmaps->find( "to_town_text" );
	text_window = new t_text_window( get_font( 16 ), layer->get_rect(), background, k_caravan_to_town_text, t_pixel_24(0,0,0) );
	text_window->set_drop_shadow( false );
	text_window->set_justification( k_justify_center );
	
	layer = m_bitmaps->find( "caravan" );
	m_caravan_window = new t_creature_array_window( layer->get_rect().top_left(), &m_caravan_army, 
													t_creature_array_window::k_single_row,
													0, background );
	m_caravan_window->set_change_handler( bound_handler( *this, &t_dialog_caravan_creation::caravan_creature_array_changed ) );

	layer = m_bitmaps->find( "garrison" );
	m_garrison_window = new t_creature_array_window( layer->get_rect().top_left(), NULL, 
													 t_creature_array_window::k_top_row,
													 0, background );
	m_garrison_window->link_selection( m_caravan_window );

	t_screen_point bottom_point = layer->get_rect().top_left();
	bottom_point.y += m_garrison_window->get_frame_height();

	m_visiting_window = new t_creature_array_window( bottom_point, NULL, 
												     t_creature_array_window::k_bottom_row,
												     0, background );
	m_visiting_window->link_selection( m_caravan_window );
	m_visiting_window->move_before( m_garrison_window );

	// Create window to get height, then correct positioning
	m_single_window = new t_creature_array_window( layer->get_rect().top_left(), NULL, 
												   t_creature_array_window::k_single_row,
												   0, background );
	m_single_window->link_selection( m_caravan_window );

	t_screen_point single_point = layer->get_rect().top_left();
	single_point.y += ( m_garrison_window->get_frame_height() + m_visiting_window->get_frame_height() - m_single_window->get_frame_height()) / 2;
	m_single_window->move( single_point );

	layer = m_bitmaps->find( "buy_button" );
	m_buy_button = new t_button( k_buy_button.get(), layer->get_rect().top_left(), background );
	m_buy_button->set_click_handler( bound_handler( *this, &t_dialog_caravan_creation::buy_clicked ) );
	help_item = &help["buy"];
	m_buy_button->set_help_balloon_text( town_replacer( help_item->name ) );
	m_buy_button->set_right_click_text( town_replacer( help_item->help_text ) );

	layer = m_bitmaps->find( "buy_portrait" );
	m_buy_portrait = new t_creature_icon_window ( layer->get_rect(), background );

	// Set up location scrollings lists
	layer = m_bitmaps->find( "location_1" );
	t_screen_rect first_location = layer->get_rect();

	t_bitmap_layer const * name_background_layer = m_bitmaps->find( "location_1_name_background" );
	t_bitmap_layer const * location_frame_layer = m_bitmaps->find( "location_1_frame" );
	t_bitmap_layer const * location_frame_highlighted_layer = m_bitmaps->find( "location_1_frame_highlighted" );

	layer = m_bitmaps->find( "location_1_picture" );
	t_screen_rect location_picture = layer->get_rect();

	layer = m_bitmaps->find( "location_1_map" );
	t_screen_rect location_map = layer->get_rect();

	layer = m_bitmaps->find( "location_1_name" );
	t_screen_rect location_name = layer->get_rect();

	int visible_count = minimum( unsigned int( k_displayed_locations ), 
								 maximum( m_locations[ k_location_type_origin ].size(), m_locations[ k_location_type_destination ].size() ) );

	for ( i = 0; i < visible_count; i++ )
	{
		t_screen_point location_offset;
		if ( i == 0 )
		{
			location_offset = first_location.top_left();
		}
		else
		{
			std::string layer_name = format_string( "location_%d", i + 1 );
			layer = m_bitmaps->find( layer_name );
			location_offset = layer->get_rect().top_left();
		}

		t_visible_location &location = m_visible_locations[i];

		t_screen_point position_diff = location_offset - first_location.top_left();

		location.button = new t_button( location_frame_layer->get_rect().top_left() + position_diff, background );
		location.button->set_click_handler( add_2nd_argument( bound_handler( *this, &t_dialog_caravan_creation::location_clicked ), i ) );

		location.picture = new t_buffer_window( location_picture.top_left() - location_frame_layer->get_rect().top_left(), location.button );
		location.map = new t_micro_map_window( location_map.top_left() - location_frame_layer->get_rect().top_left(), location.button );

		location.normal_frame = new t_bitmap_layer_window( location_frame_layer, -location_frame_layer->get_rect().top_left(), location.button );

		location.highlight_frame = new t_bitmap_layer_window( location_frame_highlighted_layer, -location_frame_layer->get_rect().top_left(), location.button );
		location.highlight_frame->set_visible( false );

		location.name_background = new t_bitmap_layer_window( name_background_layer, position_diff, background );

		location.name_window = new t_text_window( get_font( 18 ), location_name + position_diff, background, "", t_pixel_24( 0, 0, 0 ) );
		location.name_window->set_drop_shadow( false );
		location.name_window->set_justification( k_justify_center );

		location.index = i;
	}

	t_screen_rect rect = m_bitmaps->get_rect();
	rect += (m_parent_town_window->get_client_rect().size() - rect.size()) / 2;
	init( rect );

	if ( !m_locations[ k_location_type_origin ].empty() )
		set_location_type( k_location_type_origin );
	else
		set_location_type( k_location_type_destination );

	return true;
}

// ---------------------------------------------------------------------------
// Buy creatures from creature dwelling, then caravan them
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::buy_clicked( t_button * )
{
	assert( m_location_type == k_location_type_origin );
	if ( m_location_type != k_location_type_origin )
		return;

	t_location_ptr object = m_locations[ k_location_type_origin ][ m_selected_location[ k_location_type_origin ] ];

	assert( !object.is_town );
	if( object.is_town )
		return;

	t_adv_dwelling * dwelling = object.object.dwelling;


	int days;
	if ( get_travel_time_from_origin( m_selected_location[ k_location_type_origin ], days ) != k_pathfind_success )
	{
		assert( false );
		return;
	}

	t_caravan_ptr caravan = new t_caravan( m_map, m_map->get_day() + days,
										   dwelling, m_town, m_map->get_player_number() );

	dwelling->run_recruit_dialog( this, *caravan );
    m_parent_town_window->update_materials();

	if ( !caravan->empty() )
	{
		send_caravan( caravan );

		if ( days == 1 )
		{
			ok_dialog( replace_keywords( k_dwelling_caravan_sent_1_day, 
										 "%destination", m_town->get_name() ), true );
		}
		else
		{
			ok_dialog( replace_keywords( k_dwelling_caravan_sent_multiple_days,
										 "%days", format_string( "%d", days ),	
										 "%destination", m_town->get_name() ), true );
		}
	}

	update_text_and_creators();
}

// ---------------------------------------------------------------------------
// Cancel button clicked
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::cancel_clicked( t_button * )
{
	if ( !m_caravan_army.empty() )
	{
		if ( !yes_no_dialog( k_caravan_cancel_without_sending_text, true ) )
			return;

		if ( !remerge_caravan() )
			return;
	}

	if ( !unselect() )
		return;

	m_return_value = false;
	close();
}

// ---------------------------------------------------------------------------
// m_caravan_army changed
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::caravan_creature_array_changed()
{
	m_transport_button->enable( !m_caravan_army.empty() );
}

// ---------------------------------------------------------------------------
// Change to going from town to destinations
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::from_town_clicked( t_button * )
{
	if ( m_location_type != k_location_type_destination )
	{
		if ( unselect() )
			set_location_type( k_location_type_destination );
	}

	m_from_town_button->set_pressed( m_location_type == k_location_type_destination );
	m_to_town_button->set_pressed( m_location_type == k_location_type_origin );
}

// ---------------------------------------------------------------------------
// One of the locations was clicked
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::location_clicked( t_button *, int index )
{
	if ( m_selected_location[ m_location_type ] == m_visible_locations[index].index )
		return;

	if ( !unselect() )
		return;

	set_selection( m_visible_locations[index].index );
}

// ---------------------------------------------------------------------------
// Move caravan back into garrison
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::move_caravan_clicked( t_button * )
{
	if ( m_garrison_window->is_visible() )
	{
		m_garrison_window->merge( m_caravan_window );
		m_visiting_window->merge( m_caravan_window );
	}
	else
	{
		m_single_window->merge( m_caravan_window );
	}
}

// ---------------------------------------------------------------------------
// Move everything in garrison to caravan
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::move_garrison_to_caravan_clicked( t_button * )
{
	m_caravan_window->merge( m_garrison_window );
}

// ---------------------------------------------------------------------------
// Move everything in single-window garrison to caravan
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::move_single_to_caravan_clicked( t_button * )
{
	m_caravan_window->merge( m_single_window );
}

// ---------------------------------------------------------------------------
// Move everything in visiting army to caravan
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::move_visiting_to_caravan_clicked( t_button * )
{
	m_caravan_window->merge( m_visiting_window );
}

// ---------------------------------------------------------------------------
// OK: Send caravan then close window
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::ok_clicked( t_button * )
{
	if ( !m_caravan_army.empty() )
	{
		// Send caravan along
		send_current_caravan();
	}

	if ( !unselect() )
		return;

	m_return_value = true;
	close();
}

// ---------------------------------------------------------------------------
// Scrollbar changed position
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::scroll( t_scrollbar *, int position )
{
	int i;
	int location_size = m_locations[ m_location_type ].size();
	assert( position < location_size );
	assert( location_size < k_displayed_locations || position + k_displayed_locations <= location_size );

	int visible_locations = minimum( int ( k_displayed_locations ), location_size - position );

	for ( i = 0; i < visible_locations; i++ )
	{
		m_visible_locations[i].index = i + position;
		update_location( i );
	}
}

// ---------------------------------------------------------------------------
// Send without closing window
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::send_clicked( t_button * )
{
	assert( !m_caravan_army.empty() );

	if ( !m_caravan_army.empty() )
	{
		// Send caravan along
		send_current_caravan();
	}

	m_transport_button->enable( false ); 
}

// ---------------------------------------------------------------------------
// One of the split buttons was clicked
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::split_clicked( t_button * button )
{
	if (button->is_pressed())
	{
		m_garrison_window->set_divide_mode( bound_handler( *this, 
		                                    &t_dialog_caravan_creation::cancel_split_mode ));
		m_caravan_window->set_divide_mode( bound_handler( *this, 
		                                   &t_dialog_caravan_creation::cancel_split_mode ));
		m_visiting_window->set_divide_mode( bound_handler( *this, 
		                                    &t_dialog_caravan_creation::cancel_split_mode ));
		m_single_window->set_divide_mode( bound_handler( *this, 
		                                  &t_dialog_caravan_creation::cancel_split_mode ));
	}
	else
	{
		cancel_split_mode();
	}
}

// ---------------------------------------------------------------------------
// Change to going from origins to town
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::to_town_clicked( t_button * )
{
	if ( m_location_type != k_location_type_origin )
	{
		if ( unselect() )
			set_location_type( k_location_type_origin );
	}

	m_from_town_button->set_pressed( m_location_type == k_location_type_destination );
	m_to_town_button->set_pressed( m_location_type == k_location_type_origin );
}

// ---------------------------------------------------------------------------
// Cancel the "split" mode
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::cancel_split_mode()
{
	m_single_split_button->set_pressed( false );
	m_double_split_button->set_pressed( false );

	m_garrison_window->cancel_divide_mode();
	m_caravan_window->cancel_divide_mode();
	m_visiting_window->cancel_divide_mode();
	m_single_window->cancel_divide_mode();
}

// ---------------------------------------------------------------------------
// Calculate time from given origin to destination
// ---------------------------------------------------------------------------
t_dialog_caravan_creation::t_pathfind_result t_dialog_caravan_creation::get_travel_time_from_origin( int origin_index, int &days )
{
	if ( m_origin_permenantly_blocked[ origin_index ] )
		return k_pathfind_inaccessable;

	t_adventure_path_finder & path_finder = *m_origin_path_finders[ origin_index ];

	t_footprint const&			footprint = m_town->get_footprint();
	t_adv_map_point				town_origin = m_town->get_position();
	t_map_point_2d				offset;
	t_map_point_2d				footprint_size = footprint.get_size();
	t_adventure_path_data const *closest_point_data = NULL;

	// look at each point in footprint, looking for trigger cells.
	for (offset.row = 0; offset.row < footprint_size.row; offset.row++)
	{
		for (offset.column = 0; offset.column < footprint_size.column; offset.column++)
		{
			if (footprint.is_trigger_cell( offset ))
			{
				t_adventure_path_data const &data = path_finder.get_data( offset + town_origin );

				if ( data.visited )
				{
					if ( closest_point_data == NULL || closest_point_data->move_cost > data.move_cost )
					{
						closest_point_data = &data;
					}
				}
			}
		}
	}

	if ( closest_point_data == NULL )
		return k_pathfind_inaccessable;

	if ( closest_point_data->blocked_by_enemy )
		return k_pathfind_blocked;

	// Always round days up
	days = ( closest_point_data->move_cost + t_caravan::k_daily_movement - 1 ) / t_caravan::k_daily_movement;

	// Cheap insurance
	if ( days < 1 )
		days = 1;

	return k_pathfind_success;
}

// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
t_dialog_caravan_creation::t_pathfind_result t_dialog_caravan_creation::get_travel_time_to_destination( int destination_index, int &days )
{
	if ( m_town_permenantly_blocked )
		return k_pathfind_inaccessable;

	t_adventure_object const &  destination = *m_locations[ k_location_type_destination ][ destination_index ];
	t_footprint const&			footprint = destination.get_footprint();
	t_adv_map_point				dest_origin = destination.get_position();
	t_map_point_2d				offset;
	t_map_point_2d				footprint_size = footprint.get_size();
	t_adventure_path_data const *closest_point_data = NULL;

	// look at each point in footprint, looking for trigger cells.
	for (offset.row = 0; offset.row < footprint_size.row; offset.row++)
	{
		for (offset.column = 0; offset.column < footprint_size.column; offset.column++)
		{
			if (footprint.is_trigger_cell( offset ))
			{
				t_adventure_path_data const &data = m_town_pathfinder.get_data( offset + dest_origin );

				if ( data.visited )
				{
					if ( closest_point_data == NULL || closest_point_data->move_cost > data.move_cost )
					{
						closest_point_data = &data;
					}
				}
			}
		}
	}

	if ( closest_point_data == NULL )
		return k_pathfind_inaccessable;

	if ( closest_point_data->blocked_by_enemy )
		return k_pathfind_blocked;

	// Always round days up
	days = ( closest_point_data->move_cost + t_caravan::k_daily_movement - 1 ) / t_caravan::k_daily_movement;

	// Cheap insurance
	if ( days < 1 )
		days = 1;

	return k_pathfind_success;
}

// ---------------------------------------------------------------------------
// Remerge current caravan army back into current army or visitor windows
// ---------------------------------------------------------------------------
bool t_dialog_caravan_creation::remerge_caravan()
{
	t_creature_array_window * army_window1;
	t_creature_array_window * army_window2;

	if ( m_garrison_window->is_visible() )
	{
		army_window1 = m_garrison_window.get();
		army_window2 = m_visiting_window.get();
	}
	else
	{
		army_window1 = m_single_window.get();
		army_window2 = NULL;
	}

	// Try a normal merge
	army_window1->merge( m_caravan_window.get() );
	if ( army_window2 )
		army_window2->merge( m_caravan_window.get() );

	if ( m_caravan_army.empty() )
		return true;

	// Consolidate armies and try again
	t_creature_array * army1;
	t_creature_array * army2;

	army1 = army_window1->get_army();
	if ( army_window2 )
		army2 = army_window2->get_army();
	else
		army2 = NULL;

	army1->consolidate();

	if ( army2 )
		army2->consolidate();

	army_window1->merge( m_caravan_window.get() );
	if ( army_window2 )
		army_window2->merge( m_caravan_window.get() );

	if ( m_caravan_army.empty() )
		return true;

	if ( army_window2 )
	{
		// Try merging army2 into army1 to make more room
		army_window1->merge( army_window2 );
		army1->consolidate();
		army_window1->merge( m_caravan_window.get() );
		army_window2->merge( m_caravan_window.get() );

		if ( m_caravan_army.empty() )
			return true;
	}

	// Should never get here!!! Should always be able to remerge the caravan back into its source stacks
	assert( false );

	// But handle somehow
	ok_dialog( k_caravan_could_not_merge, true );
	return false;
}


// ---------------------------------------------------------------------------
// Send off the given caravan
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::send_caravan( t_caravan_ptr caravan )
{
	m_map->add_caravan( caravan );
	m_map->get_player().add( caravan );
}

// ---------------------------------------------------------------------------
// Send the caravan currently in the selection rings
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::send_current_caravan()
{
	if ( m_caravan_army.empty() )
		return;

	t_location_ptr object = m_locations[ m_location_type ][ m_selected_location[ m_location_type ] ];

	t_caravan_ptr caravan;
	
	int days;

	if ( m_location_type == k_location_type_origin )
	{
		if ( get_travel_time_from_origin( m_selected_location[ m_location_type ], days ) != k_pathfind_success )
		{
			assert( false );
			return;
		}

		caravan = new t_caravan( m_map, m_map->get_day() + days,
								 static_cast< t_adventure_object * >( object ), m_town, m_map->get_player_number() );
	}
	else
	{
		if ( get_travel_time_to_destination( m_selected_location[ m_location_type ], days ) != k_pathfind_success )
		{
			assert( false );
			return;
		}

		assert( object.is_town );
		if ( !object.is_town )
			return;

		caravan = new t_caravan( m_map, m_map->get_day() + days,
								 m_town, object.object.town, m_map->get_player_number() );
	}

	caravan->swap( m_caravan_army );

	send_caravan( caravan );

	m_caravan_window->update();
}

// ---------------------------------------------------------------------------
// Set the location list to display origins or destinations
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::set_location_type( t_location_type new_type )
{
	m_location_type = new_type;
	int new_size = m_locations[ m_location_type ].size();

	// Make sure corret location displays are visible
	int i;

	for ( i = 0; i < k_displayed_locations; i++ )
	{
		if ( m_visible_locations[i].button.get() == NULL )
			break;	// Location display never created

		bool visible = ( i < new_size );

		m_visible_locations[i].button->set_visible( visible );
		m_visible_locations[i].map->set_visible( visible );
		m_visible_locations[i].name_window->set_visible( visible );
		m_visible_locations[i].name_background->set_visible( visible );
		m_visible_locations[i].normal_frame->set_visible( visible );
		m_visible_locations[i].picture->set_visible( visible );
	}

	if ( k_displayed_locations >= new_size )
	{
		m_scrollbar->set_visible( false );
		scroll( NULL, 0 ); // Force location displays to update properly
	}
	else
	{
		m_scrollbar->set_visible( true );
		m_scrollbar->set_limits( 0, new_size - k_displayed_locations );
		int position;

		if ( m_selected_location[ m_location_type ] + k_displayed_locations > new_size )
		{
			position = new_size - k_displayed_locations;
		}
		else
		{
			position = m_selected_location[ m_location_type ];
		}

		m_scrollbar->set_position( position );

		// set_position does not always call scroll(), but we always want
		// to update the display...
		scroll( NULL, position );
	}

	m_from_town_button->set_pressed( m_location_type == k_location_type_destination );
	m_to_town_button->set_pressed( m_location_type == k_location_type_origin );

	set_selection( m_selected_location[ m_location_type ] );
}

// ---------------------------------------------------------------------------
// Prepare pathfinder for use
// ---------------------------------------------------------------------------
bool t_dialog_caravan_creation::setup_pathfinder( t_adventure_object *object, t_adventure_path_finder & path_finder )
{
	// Seed pathfinder with all points near a trigger cell. Caravans can go from any of these
	// points

	m_pathfinding_armies.push_back( new t_pathfinding_subject( m_map, m_map->get_player_number(), t_caravan::k_daily_movement ) );
	t_pathfinding_subject_ptr subject = m_pathfinding_armies.back();

	return start_object_adjacent_pathfind( path_finder, *object, 
										   *subject, k_path_search_caravan,
										   bound_handler( *subject, &t_pathfinding_subject::set_position ) );
}


// ---------------------------------------------------------------------------
// The selection has changed; update text and highlight frame
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::set_selection( int index )
{
	int old_index = m_selected_location[ m_location_type ] - m_visible_locations[0].index;
	
	if ( old_index >= 0 && old_index < k_displayed_locations )
	{
		m_visible_locations[old_index].highlight_frame->set_visible( false );
	}

	m_selected_location[ m_location_type ] = index;

	int new_index = m_selected_location[ m_location_type ] - m_visible_locations[0].index;
	
	if ( new_index >= 0 && new_index < k_displayed_locations )
	{
		m_visible_locations[new_index].highlight_frame->set_visible( true );
	}

	update_text_and_creators();
}

// ---------------------------------------------------------------------------
// Unselect the current selection. Returns false if unselection failed (keep
// current selection)
// ---------------------------------------------------------------------------
bool t_dialog_caravan_creation::unselect( )
{
	if ( !m_caravan_army.empty() )
	{
		if ( !yes_no_dialog( k_caravan_change_without_sending_text, true ) )
			return false;

		if ( !remerge_caravan() )
			return false;
	}

	cancel_split_mode();

	if ( m_visiting_army.get() != NULL )
	{
		t_adventure_frame * frame = m_map->get_map_window()->get_frame();

		t_town * town;

		if ( m_location_type == k_location_type_destination )
		{
			town = m_town;
		}
		else
		{
			t_location_ptr & location = m_locations[ m_location_type ][ m_selected_location[ m_location_type ] ];

			assert( location.is_town );
		
			town = location.object.town;
		}

		t_army * adjacent_army = frame->create_army( town, m_visiting_army, m_temp_army);
		m_parent_town_window->set_trading_army( town, adjacent_army );

		frame->update_army( m_visiting_army ); // Will destroy visiting army
	}

	m_visiting_window->set_army( NULL );
	m_visiting_army = NULL;
	m_temp_army = NULL;

	return true;
}

// ---------------------------------------------------------------------------
// Make sure the given location display accurately reflects the current 
// item it is displaying
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::update_location( int index )
{
	int days;
	t_pathfind_result pathfind_result;
	int location_index = m_visible_locations[ index ].index;
	t_location_ptr object = m_locations[ m_location_type ][ location_index ];

	if ( m_location_type == k_location_type_destination )
	{
		pathfind_result = get_travel_time_to_destination( location_index, days );
	}
	else
	{
		pathfind_result = get_travel_time_from_origin( location_index, days );
	}

	std::string location_name;

	if ( pathfind_result == k_pathfind_success )
	{
		location_name = replace_keywords( k_caravan_location_title,
										  "%name", object->get_name(),
										  "%days", format_string( "%d", days ) );
	}
	else
	{
		location_name = replace_keywords( k_caravan_unreachable_location_title,
										  "%name", object->get_name() );
	}

	m_visible_locations[ index ].name_window->set_text( location_name );
	
	// Draw map & thumbnail
	if ( object.is_town )
	{
		m_image_creator.set_town( object.object.town );
	}
	else
	{
		m_image_creator.set_dwelling( object.object.dwelling );
	}

	m_visible_locations[ index ].picture->set_bitmap( m_image_creator.get_bitmap() );

	t_screen_point map_size = m_bitmaps->find( "location_1_map" )->get_rect().size();
	m_visible_locations[ index ].map->set_renderer(
		&m_image_creator.get_map_renderer( *m_map, m_map->get_player().get_team(), map_size, g_town_marker.get() ) );

	m_visible_locations[ index ].button->set_released_image( m_visible_locations[ index ].picture );
	m_visible_locations[ index ].button->set_visible( true );

	m_visible_locations[ index ].highlight_frame->set_visible( m_visible_locations[ index ].index == m_selected_location[ m_location_type ] );
}


// ---------------------------------------------------------------------------
// Update the main window text message ( the one explaining to the user what
// he's currently doing ) and the caravan creation controls ( the buy portrait
// and button or the rings )
// ---------------------------------------------------------------------------
void t_dialog_caravan_creation::update_text_and_creators()
{
	t_location_ptr object = m_locations[ m_location_type ][ m_selected_location[ m_location_type ] ];
	int days;
	t_pathfind_result pathfind_result;

	if ( object.is_town )
	{
		t_town * origin;
		t_town * destination;

		if ( m_location_type == k_location_type_origin )
		{
			origin = object.object.town;
			destination = m_town;
			pathfind_result = get_travel_time_from_origin( m_selected_location[ m_location_type ], days );
		}
		else
		{
			origin = m_town;
			destination = object.object.town;

			pathfind_result = get_travel_time_to_destination( m_selected_location[ m_location_type ], days );
		}

		bool caravan_visible;

		switch ( pathfind_result )
		{
			case k_pathfind_success: 
				if ( days == 1 )
				{
					m_text_window->set_text( replace_keywords( k_caravan_reachable_1_day_text,
						                                       "%origin", origin->get_name(),
															   "%destination", destination->get_name() ) );
				}
				else
				{
					m_text_window->set_text( replace_keywords( k_caravan_reachable_multiple_day_text,
						                                       "%origin", origin->get_name(),
															   "%destination", destination->get_name(),
															   "%days", format_string( "%d", days ) ) );
				}
				caravan_visible = true;
				break;

			case k_pathfind_blocked:
				m_text_window->set_text( replace_keywords( k_caravan_blocked_by_enemy_text,
														   "%origin", origin->get_name(),
														   "%destination", destination->get_name() ) );
				caravan_visible = false;
				break;

			case k_pathfind_inaccessable:
				m_text_window->set_text( replace_keywords( k_caravan_permenantly_blocked_text,
														   "%origin", origin->get_name(),
														   "%destination", destination->get_name() ) );
				caravan_visible = false;
				break;

			default:
				assert( false );
				return;
		}

		// Set buy controls to invisible
		m_buy_button->set_visible( false );
		m_buy_portrait->set_visible( false );
		m_buy_text_background->set_visible( false );
		m_buy_text_window->set_visible( false );

		// Set creature array windows to visible as needed
		m_visiting_army = m_parent_town_window->get_trading_army( origin );
		t_player & player = m_map->get_player();
		int player_number = m_map->get_player_number();

		if ( m_visiting_army.get() == NULL && player.can_create_army() )
		{
			t_adv_map_point point;

			m_temp_army = new t_army;
			m_temp_army->set_owner( m_map->get_player_number() );

			if (origin->find_adjacent_space( point, *m_temp_army ))
			{
				// We can create an army if needed
				m_visiting_army = m_temp_army;
				m_visiting_army->place( *m_map, point );
			}
			else
			{
				m_temp_army = NULL;
			}
		}

		bool double_rings_visible = ( m_visiting_army.get() != NULL && origin->get_owner_number() == player_number );

		m_visiting_window->set_army( m_visiting_army );
		m_garrison_window->set_army( &origin->get_garrison() );

		if ( !double_rings_visible )
		{
			if ( origin->get_owner_number() == player_number )
			{
				m_single_window->set_army( &origin->get_garrison() );
				m_move_single_to_caravan_button->set_help_balloon_text( m_move_garrison_to_caravan_button->get_help_balloon_text() );
				m_move_single_to_caravan_button->set_right_click_text( m_move_garrison_to_caravan_button->get_right_click_text() );
			}
			else
			{
				m_single_window->set_army( m_visiting_army );
				m_move_single_to_caravan_button->set_help_balloon_text( m_move_visiting_to_caravan_button->get_help_balloon_text() );
				m_move_single_to_caravan_button->set_right_click_text( m_move_visiting_to_caravan_button->get_right_click_text() );
			}
		}

		m_garrison_title_background->set_visible( true );
		m_garrison_title->set_visible( true );

		m_double_rings->set_visible( double_rings_visible );
		m_double_split_button->set_visible( double_rings_visible );
		m_garrison_window->set_visible( double_rings_visible );
		m_move_garrison_to_caravan_button->set_visible( double_rings_visible && caravan_visible );
		m_visiting_window->set_visible( double_rings_visible );
		m_move_visiting_to_caravan_button->set_visible( double_rings_visible && caravan_visible );
		m_single_rings->set_visible( !double_rings_visible );
		m_move_single_to_caravan_button->set_visible( !double_rings_visible && caravan_visible );
		m_single_split_button->set_visible( !double_rings_visible );
		m_single_window->set_visible( !double_rings_visible );

		m_caravan_rings->set_visible( caravan_visible );
		m_caravan_title_background->set_visible( caravan_visible ); 
		m_caravan_title->set_visible( caravan_visible );
		m_caravan_window->set_visible( caravan_visible );
		m_move_caravan_button->set_visible( caravan_visible );

		m_text_background->set_visible( true );
		m_text_window->set_visible( true );

		// Hack: allow resurrection to put up messages, but not bonus buildings
		resurrect_heroes( *origin, k_text_resurrect_heroes, this );

		// If the trading army has dead heroes, resurrect them now	
		if ( m_visiting_army )
		{
			// Hack: allow resurrection to put up messages, but not bonus buildings
			resurrect_heroes( *m_visiting_army, k_text_resurrect_heroes, this );
			
			m_visiting_army->visit_town( origin );
		}

		// Don't put up messages
		origin->check_bonus_buildings( m_visiting_army, NULL );

		m_visiting_window->update();
		m_garrison_window->update();
		m_single_window->update();
	}
	else
	{
		assert( m_location_type == k_location_type_origin );

		t_adv_dwelling * origin = object.object.dwelling;
		t_town * destination = m_town;
		pathfind_result = get_travel_time_from_origin( m_selected_location[ m_location_type ], days );

		int population = origin->get_population();
		t_creature_type creature_type = origin->get_creature_type();
		t_creature creature( creature_type, population );
		bool can_buy;
		t_hero_keyword_replacer replacer;

		replacer.add_creature( population, creature_type, false );
		replacer.add_keyword( "%origin", origin->get_name() );
		replacer.add_keyword( "%destination", destination->get_name() );
		replacer.add_keyword( "%population", format_string( "%d", population ) );

		switch (pathfind_result)
		{
			case k_pathfind_success:
				replacer.add_keyword( "%days", format_string( "%d", days ) );

				if ( population <= 0 )
				{
					if ( days == 1 )
					{
						m_buy_text_window->set_text( replacer( k_caravan_buy_none_1_day ) );
					}
					else
					{
						m_buy_text_window->set_text( replacer( k_caravan_buy_none_multiple_days ) );
					}
					can_buy = false;
				}
				else if ( population == 1 )
				{
					if ( days == 1 )
					{
						m_buy_text_window->set_text( replacer( k_caravan_buy_one_1_day ) );
					}
					else
					{
						m_buy_text_window->set_text( replacer( k_caravan_buy_one_multiple_days ) );
					}
					can_buy = true;
				}
				else
				{
					if ( days == 1 )
					{
						m_buy_text_window->set_text( replacer( k_caravan_buy_multiple_1_day ) );
					}
					else
					{
						m_buy_text_window->set_text( replacer( k_caravan_buy_multiple_multiple_days ) );
					}
					can_buy = true;
				}
				break;

			case k_pathfind_blocked:
				if ( population <= 0 )
				{
					m_buy_text_window->set_text( replacer( k_caravan_buy_none_blocked_by_enemy ) );
				}
				else if ( population == 1 )
				{
					m_buy_text_window->set_text( replacer( k_caravan_buy_one_blocked_by_enemy ) );
				}
				else
				{
					m_buy_text_window->set_text( replacer( k_caravan_buy_multiple_blocked_by_enemy ) );
				}
				can_buy = false;
				break;

			case k_pathfind_inaccessable:
				if ( population <= 0 )
				{
					m_buy_text_window->set_text( replacer( k_caravan_buy_none_permenantly_blocked ) );
				}
				else if ( population == 1 )
				{
					m_buy_text_window->set_text( replacer( k_caravan_buy_one_permenantly_blocked ) );
				}
				else
				{
					m_buy_text_window->set_text( replacer( k_caravan_buy_multiple_permenantly_blocked ) );
				}
				can_buy = false;
				break;

			default:
				assert( false );
				return;
		}

		m_buy_portrait->set_visible( true );
		m_buy_portrait->set_creature( &creature );
		m_buy_button->set_visible( true );
		m_buy_button->enable( can_buy );
		m_buy_text_background->set_visible( true );
		m_buy_text_window->set_visible( true );

		m_garrison_title_background->set_visible( false );
		m_garrison_title->set_visible( false );
		m_double_rings->set_visible( false );
		m_double_split_button->set_visible( false );
		m_garrison_window->set_visible( false );
		m_visiting_window->set_visible( false );
		m_single_rings->set_visible( false );
		m_single_split_button->set_visible( false );
		m_single_window->set_visible( false );
		m_caravan_rings->set_visible( false );
		m_caravan_title_background->set_visible( false ); 
		m_caravan_title->set_visible( false );
		m_caravan_window->set_visible( false );
		m_text_background->set_visible( false );
		m_text_window->set_visible( false );
		m_move_garrison_to_caravan_button->set_visible( false );
		m_move_visiting_to_caravan_button->set_visible( false );
		m_move_single_to_caravan_button->set_visible( false );
		m_move_caravan_button->set_visible( false );
	}

	m_transport_button->enable( false ); // Always starts disabled
}
